/*   Valhalla MailChecker -- Simple IMAP Mail Checker
*    Copyright (C) 2010-2011  Guillaume Florimond (gflorimond at gmail dot com)
*
*    This program is free software: you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation, either version 3 of the License, or
*    any later version.
*
*    This program is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

package fr.valhalla.mailcheck;

import java.io.IOException;
import java.security.Security;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Properties;
import javax.mail.Address;
import javax.mail.BodyPart;
import javax.mail.Flags;
import javax.mail.Flags.Flag;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Multipart;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;

/**
 *
 * @author guillaume
 */
public class IMAPConnection extends Thread {

    private String login;
    private String password;

    private String protocol;
    private String host;
    private int port;
    private boolean ssl;

    private Session session;
    private Store store;
    private Folder folder;
    private Message[] mailbox;

    public IMAPConnection() {
        this.run();
    }

    public boolean openConnection(String login, String password, String protocol, String host, int port, boolean ssl) {
        System.out.println("Opening connection...");
        this.login = login;
        this.password = password;
        this.protocol = protocol;
        this.host = host;
        this.port = port;
        this.ssl = ssl;

        Properties props = System.getProperties();
        System.out.println("Property created : " + props);

        // Connexion SSL !
        if(ssl == true)
        {
            Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
            // set this session up to use SSL for IMAP connections
            props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            // don't fallback to normal IMAP connections on failure.
            props.setProperty("mail.imap.socketFactory.fallback", "false");
            // use the simap port for imap/ssl connections.
            props.setProperty("mail.imap.socketFactory.port", "993");
        }

        // Créer la session
        session = Session.getDefaultInstance(props);
        session.setDebug(false);
        System.out.println("Session created.");

        // Créer un conteneur (storage) pour les messages
        store = null;
        try {
            store = session.getStore(protocol);
            System.out.println("Store created.");
        } catch(javax.mail.NoSuchProviderException e) {
            System.out.println("Store creation failure : \n" + e);
            return false;
        }

        // Effectuer la connexion
        try {
            store.connect(host, port, login, password);
            System.out.println("Connected.");
        }
        catch(javax.mail.MessagingException e) {
            System.out.println("Error connecting to mail server : \n" + e);
            return false;
        }
        
        return true;
    }

    public boolean closeConnection() {
        try {
            // folder.expunge(); // imap expunge ?
            store.close();
        } catch (javax.mail.MessagingException e) {
            return false;
        }

        return true;
    }

    public boolean openMailBox(String mailbox) {
        // ouverture du répertoire courant INBOX
        folder = null;
        try {
            folder = store.getDefaultFolder();

            if (folder == null) {
                System.out.println("Pas de boite aux lettres par défaut");
                return false;
            }

            // par défaut on récupère les messages dans INBOX
            folder = folder.getFolder(mailbox);
            if (folder == null) {
                System.out.println("pas de inbox");
            }

            try {
                folder.open(Folder.READ_WRITE);
            } catch (javax.mail.MessagingException e) {
                System.err.println("[process_folder]: cannot open folder " + folder
                        + ": " + e.getMessage());
                e.printStackTrace();
            }

        } catch (javax.mail.MessagingException e) {

            return false;
        }

        try {
            this.mailbox = new Message[folder.getMessageCount()];
            this.mailbox = folder.getMessages();
        } catch (javax.mail.MessagingException e) {
        }

        return true;
    }

    public int countStoredMessages() {
        return mailbox.length;
    }

    public int countAllMessages() {
        int count;
        try {
            count = folder.getMessageCount();
        } catch (javax.mail.MessagingException e) {
            return -1;
        }
        return count;
    }

    public int countUnreadMessages() {
        int count;
        try {
            count = folder.getUnreadMessageCount();
        } catch (javax.mail.MessagingException e) {
            return -1;
        }
        return count;
    }

    public int countNewMessages() {
        int count;
        try {
            count = folder.getNewMessageCount();
        } catch (javax.mail.MessagingException e) {
            return -1;
        }
        return count;
    }

    public int countReadMessages() {
        return countAllMessages() - countUnreadMessages();
    }

    public int countOldMessages() {
        return countAllMessages() - countNewMessages();
    }

    public boolean deleteMessage(int num) {
        try {
            mailbox[num].setFlag(Flags.Flag.DELETED, true);
            return true;
        } catch (javax.mail.MessagingException e) {
            return false;
        }
    }

    public String getMessageSubject(int num) {
        try {
            return mailbox[num].getSubject();
        } catch (javax.mail.MessagingException e) {
            return null;
        }
    }

    public String getFromAddress(int num) {
        Address[] addr;
        InternetAddress iaddr;
        try {
            addr = mailbox[num].getFrom();
            iaddr = new InternetAddress(addr[0].toString());
            return iaddr.getPersonal();
        } catch (javax.mail.MessagingException e) {
            return null;
        }
    }

    @SuppressWarnings("static-access")
    public String getMessageDate(int num) {
        GregorianCalendar myCalendar = new GregorianCalendar();
        String myDate = new String();
        String temp = new String();

        try {
            myCalendar.setTime(mailbox[num].getReceivedDate());

            switch (myCalendar.get(myCalendar.DAY_OF_WEEK)) {
                case Calendar.SUNDAY:
                    temp = "dimanche ";
                    break;
                case Calendar.MONDAY:
                    temp = "lundi ";
                    break;
                case Calendar.TUESDAY:
                    temp = "mardi ";
                    break;
                case Calendar.WEDNESDAY:
                    temp = "mercredi ";
                    break;
                case Calendar.THURSDAY:
                    temp = "jeudi ";
                    break;
                case Calendar.FRIDAY:
                    temp = "vendredi ";
                    break;
                case Calendar.SATURDAY:
                    temp = "samedi ";
                    break;
            }
            myDate = temp;

            Integer i = new Integer(myCalendar.get(myCalendar.DATE));
            myDate += i.toString();

            switch (myCalendar.get(myCalendar.MONTH)) {
                case 0:
                    temp = " janvier";
                    break;
                case 1:
                    temp = " février";
                    break;
                case 2:
                    temp = " mars";
                    break;
                case 3:
                    temp = " avril";
                    break;
                case 4:
                    temp = " mai";
                    break;
                case 5:
                    temp = " juin";
                    break;
                case 6:
                    temp = " juillet";
                    break;
                case 7:
                    temp = " août";
                    break;
                case 8:
                    temp = " septembre";
                    break;
                case 9:
                    temp = " octobre";
                    break;
                case 10:
                    temp = " novembre";
                    break;
                case 11:
                    temp = " décembre";
                    break;
            }
            myDate += temp;

            return myDate;
        } catch (javax.mail.MessagingException e) {
            return null;
        }
    }

    public String getMessageBody(int num) {

        Multipart myMulti;
        BodyPart myBody;

        try {
            if (mailbox[num].isMimeType("text/plain")) {
                mailbox[num].setFlag(Flags.Flag.SEEN, true);
                return (String) mailbox[num].getContent();
            } else {
                myMulti = (Multipart) (mailbox[num].getContent());
                myBody = myMulti.getBodyPart(0);
                mailbox[num].setFlag(Flags.Flag.SEEN, true);
                return (String) myBody.getContent();
            }
        } catch (javax.mail.MessagingException e) {
            return null;
        } catch (IOException io) {
            return null;
        } catch(Exception ex) {
            return null;
        }
    }

    public boolean isNew(int num) {
        try {
            return mailbox[num].isSet(Flag.RECENT);
        } catch (javax.mail.MessagingException e) {
            return false;
        }
    }

    public boolean isRead(int num) {
        try {
            return mailbox[num].isSet(Flag.SEEN);
        } catch (javax.mail.MessagingException e) {
            return false;
        }
    }

    public Message getMessage(int id) {
        return mailbox[id];
    }
    

    @Override
    public void run() {
        super.run();
    }



}
